Parameters for each preprocessing step

Parameters for sc_trim_barcode

File paths

  • input fastq1: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.R2.fastq.gz
  • input fastq2: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.R1.fastq.gz
  • output fastq: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.fastq.gz

Read structure

assume read1 contains the transcript

  • barcode in read1: NA
  • barcode in read2: start at position 6, length 7
  • UMI in read2: start at position 0, length 6

Read filter

  • remove reads that have N in its barcode or UMI: FALSE
  • remove reads with low quality: TRUE
    • minimum read quality: 20
    • maximum number of base below minimum read quality: 2

Parameters for alignment

  • input fastq: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.fastq.gz
  • output bam file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.subread.bam
  • genome index: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/GRCm38.p6/GRCm38_with_ERCC

Parameters for sc_exon_mapping

  • input bam file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.subread.bam
  • output bam file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.exon.bam
  • transctiptome annotations: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/GRCm38.p6/gencode.vM18.primary_assembly.annotation.gff3, /stornext/Home/data/allstaff/h/hickey/R/x86_64-pc-linux-gnu-library/3.6/scPipe/extdata/ERCC92_anno.gff3
  • do strand specific mapping: TRUE
  • fix chromosome names: FALSE

Parameters for sc_demultiplex

  • input bam file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.combined.exon.bam
  • output folder: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279
  • barcode annotation file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.barcode_annotation.csv
  • maximum mismatch allowed in barcode: 1

Parameters for sc_gene_counting

  • output folder: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279
  • barcode annotation file: /stornext/General/data/user_managed/grpu_mritchie_1/hickey/SCORE/C075_Grant_Coultas/extdata/NN158/scPipe/LC279/LC279.barcode_annotation.csv
  • UMI correction: simple correction and merge UMI with distance 1
  • gene filtering: FALSE

Data summary

The organism is “mmusculus_gene_ensembl”, and gene id type is “ensembl_gene_id”.

Overall barcode statistics

if (is.null(params$organism) || is.na(params$organism)) {
  sce = create_sce_by_dir(params$outdir)
} else {
  sce = create_sce_by_dir(params$outdir, organism=params$organism, gene_id_type=params$gene_id_type)
}
overall_stat = demultiplex_info(sce)
datatable(overall_stat, width=800)

Plot barcode match statistics in pie chart:

plot_demultiplex(sce)

Read alignment statistics

ggplotly(plot_mapping(sce, dataname=params$samplename, percentage = FALSE))
ggplotly(plot_mapping(sce, dataname=params$samplename, percentage = TRUE))

Summary and distributions of QC metrics

if (any(colSums(counts(sce)) == 0)) {
  zero_cells = sum(colSums(counts(sce)) == 0)
  sce = sce[, colSums(counts(sce)) > 0]
} else {
  zero_cells = 0
}

Datatable of all QC metrics:

sce = calculate_QC_metrics(sce)
if(!all(colSums(as.data.frame(QC_metrics(sce)))>0)){
  QC_metrics(sce) = QC_metrics(sce)[, colSums(as.data.frame(QC_metrics(sce)))>0]
}
datatable(as.data.frame(QC_metrics(sce)), width=800, options=list(scrollX= TRUE))

Summary of all QC metrics:

datatable(do.call(cbind, lapply(QC_metrics(sce), summary)), width=800, options=list(scrollX= TRUE))

Number of reads mapped to exon before UMI deduplication VS number of genes detected:

ggplotly(ggplot(as.data.frame(QC_metrics(sce)), aes(x=mapped_to_exon, y=number_of_genes))+geom_point(alpha=0.8))

knitr::knit_exit()
LS0tCnRpdGxlOiAic2NQaXBlIHJlcG9ydCBmb3Igc2FtcGxlIGByIHBhcmFtcyRzYW1wbGVuYW1lYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCnBhcmFtczoKICBzYW1wbGVuYW1lOiAiTEMyNzkiCiAgZnExOiAiL3N0b3JuZXh0L0dlbmVyYWwvZGF0YS91c2VyX21hbmFnZWQvZ3JwdV9tcml0Y2hpZV8xL2hpY2tleS9TQ09SRS9DMDc1X0dyYW50X0NvdWx0YXMvZXh0ZGF0YS9OTjE1OC9zY1BpcGUvTEMyNzkvTEMyNzkuUjIuZmFzdHEuZ3oiCiAgZnEyOiAiL3N0b3JuZXh0L0dlbmVyYWwvZGF0YS91c2VyX21hbmFnZWQvZ3JwdV9tcml0Y2hpZV8xL2hpY2tleS9TQ09SRS9DMDc1X0dyYW50X0NvdWx0YXMvZXh0ZGF0YS9OTjE1OC9zY1BpcGUvTEMyNzkvTEMyNzkuUjEuZmFzdHEuZ3oiCiAgZnFvdXQ6ICIvc3Rvcm5leHQvR2VuZXJhbC9kYXRhL3VzZXJfbWFuYWdlZC9ncnB1X21yaXRjaGllXzEvaGlja2V5L1NDT1JFL0MwNzVfR3JhbnRfQ291bHRhcy9leHRkYXRhL05OMTU4L3NjUGlwZS9MQzI3OS9MQzI3OS5jb21iaW5lZC5mYXN0cS5neiIKICBiYzFfaW5mbzogIk5BIgogIGJjMl9pbmZvOiAic3RhcnQgYXQgcG9zaXRpb24gNiwgbGVuZ3RoIDciCiAgdW1pX2luZm86ICJzdGFydCBhdCBwb3NpdGlvbiAwLCBsZW5ndGggNiIKICBybV9uOiBGQUxTRQogIHJtX2xvdzogVFJVRQogIG1pbl9xOiAyMAogIG51bV9icTogMgogIGJhbV9hbGlnbjogIi9zdG9ybmV4dC9HZW5lcmFsL2RhdGEvdXNlcl9tYW5hZ2VkL2dycHVfbXJpdGNoaWVfMS9oaWNrZXkvU0NPUkUvQzA3NV9HcmFudF9Db3VsdGFzL2V4dGRhdGEvTk4xNTgvc2NQaXBlL0xDMjc5L0xDMjc5LmNvbWJpbmVkLnN1YnJlYWQuYmFtIgogIGdfaW5kZXg6ICIvc3Rvcm5leHQvR2VuZXJhbC9kYXRhL3VzZXJfbWFuYWdlZC9ncnB1X21yaXRjaGllXzEvaGlja2V5L1NDT1JFL0MwNzVfR3JhbnRfQ291bHRhcy9leHRkYXRhL0dSQ20zOC5wNi9HUkNtMzhfd2l0aF9FUkNDIgogIGJhbV9tYXA6ICIvc3Rvcm5leHQvR2VuZXJhbC9kYXRhL3VzZXJfbWFuYWdlZC9ncnB1X21yaXRjaGllXzEvaGlja2V5L1NDT1JFL0MwNzVfR3JhbnRfQ291bHRhcy9leHRkYXRhL05OMTU4L3NjUGlwZS9MQzI3OS9MQzI3OS5jb21iaW5lZC5leG9uLmJhbSIKICBvdXRkaXI6ICIvc3Rvcm5leHQvR2VuZXJhbC9kYXRhL3VzZXJfbWFuYWdlZC9ncnB1X21yaXRjaGllXzEvaGlja2V5L1NDT1JFL0MwNzVfR3JhbnRfQ291bHRhcy9leHRkYXRhL05OMTU4L3NjUGlwZS9MQzI3OSIKICBhbm5vX2dmZjogIi9zdG9ybmV4dC9HZW5lcmFsL2RhdGEvdXNlcl9tYW5hZ2VkL2dycHVfbXJpdGNoaWVfMS9oaWNrZXkvU0NPUkUvQzA3NV9HcmFudF9Db3VsdGFzL2V4dGRhdGEvR1JDbTM4LnA2L2dlbmNvZGUudk0xOC5wcmltYXJ5X2Fzc2VtYmx5LmFubm90YXRpb24uZ2ZmMywgL3N0b3JuZXh0L0hvbWUvZGF0YS9hbGxzdGFmZi9oL2hpY2tleS9SL3g4Nl82NC1wYy1saW51eC1nbnUtbGlicmFyeS8zLjYvc2NQaXBlL2V4dGRhdGEvRVJDQzkyX2Fubm8uZ2ZmMyIKICBzdG5kOiBUUlVFCiAgZml4X2NocjogRkFMU0UKICBiY19hbm5vOiAiL3N0b3JuZXh0L0dlbmVyYWwvZGF0YS91c2VyX21hbmFnZWQvZ3JwdV9tcml0Y2hpZV8xL2hpY2tleS9TQ09SRS9DMDc1X0dyYW50X0NvdWx0YXMvZXh0ZGF0YS9OTjE1OC9zY1BpcGUvTEMyNzkvTEMyNzkuYmFyY29kZV9hbm5vdGF0aW9uLmNzdiIKICBtYXhfbWlzOiAxCiAgVU1JX2NvcjogInNpbXBsZSBjb3JyZWN0aW9uIGFuZCBtZXJnZSBVTUkgd2l0aCBkaXN0YW5jZSAxIgogIGdlbmVfZmw6IEZBTFNFCiAgb3JnYW5pc206ICJtbXVzY3VsdXNfZ2VuZV9lbnNlbWJsIgogIGdlbmVfaWRfdHlwZTogImVuc2VtYmxfZ2VuZV9pZCIKCi0tLQpgYGB7ciwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShzY2FsZXMpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoRFQpCmxpYnJhcnkoc2NhdGVyKQpsaWJyYXJ5KHNjcmFuKQpsaWJyYXJ5KHNjUGlwZSkKbGlicmFyeShSdHNuZSkKYGBgCgojIFBhcmFtZXRlcnMgZm9yIGVhY2ggcHJlcHJvY2Vzc2luZyBzdGVwCgojIyBQYXJhbWV0ZXJzIGZvciBgc2NfdHJpbV9iYXJjb2RlYAoKIyMjIEZpbGUgcGF0aHMKCiogaW5wdXQgZmFzdHExOiBgciBwYXJhbXMkZnExYAoqIGlucHV0IGZhc3RxMjogYHIgcGFyYW1zJGZxMmAKKiBvdXRwdXQgZmFzdHE6IGByIHBhcmFtcyRmcW91dGAKCiMjIyBSZWFkIHN0cnVjdHVyZQoKYXNzdW1lIHJlYWQxIGNvbnRhaW5zIHRoZSB0cmFuc2NyaXB0CgoqIGJhcmNvZGUgaW4gcmVhZDE6IGByIHBhcmFtcyRiYzFfaW5mb2AKKiBiYXJjb2RlIGluIHJlYWQyOiBgciBwYXJhbXMkYmMyX2luZm9gCiogVU1JIGluIHJlYWQyOiBgciBwYXJhbXMkdW1pX2luZm9gCgojIyMgUmVhZCBmaWx0ZXIKCiogcmVtb3ZlIHJlYWRzIHRoYXQgaGF2ZSBgTmAgaW4gaXRzIGJhcmNvZGUgb3IgVU1JOiBgciBwYXJhbXMkcm1fbmAKKiByZW1vdmUgcmVhZHMgd2l0aCBsb3cgcXVhbGl0eTogYHIgcGFyYW1zJHJtX2xvd2AKYHIgaWYgKHBhcmFtcyRybV9sb3cpe3Bhc3RlKCJcdCogbWluaW11bSByZWFkIHF1YWxpdHk6IiwgcGFyYW1zJG1pbl9xLCAiXG4iLCAiXHQqIG1heGltdW0gbnVtYmVyIG9mIGJhc2UgYmVsb3cgbWluaW11bQpyZWFkIHF1YWxpdHk6IiwgcGFyYW1zJG51bV9icSwgIlxuIil9YAoKIyMgUGFyYW1ldGVycyBmb3IgYWxpZ25tZW50CgoqIGlucHV0IGZhc3RxOiBgciBwYXJhbXMkZnFvdXRgCiogb3V0cHV0IGJhbSBmaWxlOiBgciBwYXJhbXMkYmFtX2FsaWduYAoqIGdlbm9tZSBpbmRleDogYHIgcGFyYW1zJGdfaW5kZXhgCgojIyBQYXJhbWV0ZXJzIGZvciBgc2NfZXhvbl9tYXBwaW5nYAoKKiBpbnB1dCBiYW0gZmlsZTogYHIgcGFyYW1zJGJhbV9hbGlnbmAKKiBvdXRwdXQgYmFtIGZpbGU6IGByIHBhcmFtcyRiYW1fbWFwYAoqIHRyYW5zY3RpcHRvbWUgYW5ub3RhdGlvbnM6IGByIHBhcmFtcyRhbm5vX2dmZmAKKiBkbyBzdHJhbmQgc3BlY2lmaWMgbWFwcGluZzogYHIgcGFyYW1zJHN0bmRgCiogZml4IGNocm9tb3NvbWUgbmFtZXM6IGByIHBhcmFtcyRmaXhfY2hyYAoKIyMgUGFyYW1ldGVycyBmb3IgYHNjX2RlbXVsdGlwbGV4YAoKKiBpbnB1dCBiYW0gZmlsZTogYHIgcGFyYW1zJGJhbV9tYXBgCiogb3V0cHV0IGZvbGRlcjogYHIgcGFyYW1zJG91dGRpcmAKKiBiYXJjb2RlIGFubm90YXRpb24gZmlsZTogYHIgcGFyYW1zJGJjX2Fubm9gCiogbWF4aW11bSBtaXNtYXRjaCBhbGxvd2VkIGluIGJhcmNvZGU6IGByIHBhcmFtcyRtYXhfbWlzYAoKIyMgUGFyYW1ldGVycyBmb3IgYHNjX2dlbmVfY291bnRpbmdgCgoqIG91dHB1dCBmb2xkZXI6IGByIHBhcmFtcyRvdXRkaXJgCiogYmFyY29kZSBhbm5vdGF0aW9uIGZpbGU6IGByIHBhcmFtcyRiY19hbm5vYAoqIFVNSSBjb3JyZWN0aW9uOiBgciBwYXJhbXMkVU1JX2NvcmAKKiBnZW5lIGZpbHRlcmluZzogYHIgcGFyYW1zJGdlbmVfZmxgCgojIERhdGEgc3VtbWFyeQoKVGhlIG9yZ2FuaXNtIGlzICJgciBwYXJhbXMkb3JnYW5pc21gIiwgYW5kIGdlbmUgaWQgdHlwZSBpcyAiYHIgcGFyYW1zJGdlbmVfaWRfdHlwZWAiLgoKIyMgT3ZlcmFsbCBiYXJjb2RlIHN0YXRpc3RpY3MKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQppZiAoaXMubnVsbChwYXJhbXMkb3JnYW5pc20pIHx8IGlzLm5hKHBhcmFtcyRvcmdhbmlzbSkpIHsKICBzY2UgPSBjcmVhdGVfc2NlX2J5X2RpcihwYXJhbXMkb3V0ZGlyKQp9IGVsc2UgewogIHNjZSA9IGNyZWF0ZV9zY2VfYnlfZGlyKHBhcmFtcyRvdXRkaXIsIG9yZ2FuaXNtPXBhcmFtcyRvcmdhbmlzbSwgZ2VuZV9pZF90eXBlPXBhcmFtcyRnZW5lX2lkX3R5cGUpCn0Kb3ZlcmFsbF9zdGF0ID0gZGVtdWx0aXBsZXhfaW5mbyhzY2UpCmRhdGF0YWJsZShvdmVyYWxsX3N0YXQsIHdpZHRoPTgwMCkKYGBgCgpQbG90IGJhcmNvZGUgbWF0Y2ggc3RhdGlzdGljcyBpbiBwaWUgY2hhcnQ6CmBgYHtyfQpwbG90X2RlbXVsdGlwbGV4KHNjZSkKYGBgCgojIyBSZWFkIGFsaWdubWVudCBzdGF0aXN0aWNzCgpgYGB7cn0KZ2dwbG90bHkocGxvdF9tYXBwaW5nKHNjZSwgZGF0YW5hbWU9cGFyYW1zJHNhbXBsZW5hbWUsIHBlcmNlbnRhZ2UgPSBGQUxTRSkpCmBgYAoKYGBge3J9CmdncGxvdGx5KHBsb3RfbWFwcGluZyhzY2UsIGRhdGFuYW1lPXBhcmFtcyRzYW1wbGVuYW1lLCBwZXJjZW50YWdlID0gVFJVRSkpCmBgYAoKIyMgU3VtbWFyeSBhbmQgZGlzdHJpYnV0aW9ucyBvZiBRQyBtZXRyaWNzCgpgYGB7cn0KaWYgKGFueShjb2xTdW1zKGNvdW50cyhzY2UpKSA9PSAwKSkgewogIHplcm9fY2VsbHMgPSBzdW0oY29sU3Vtcyhjb3VudHMoc2NlKSkgPT0gMCkKICBzY2UgPSBzY2VbLCBjb2xTdW1zKGNvdW50cyhzY2UpKSA+IDBdCn0gZWxzZSB7CiAgemVyb19jZWxscyA9IDAKfQpgYGAKCmByIGlmICh6ZXJvX2NlbGxzID4gMCl7cGFzdGUoemVyb19jZWxscywgImNlbGxzIGhhdmUgemVybyByZWFkIGNvdW50cywgcmVtb3ZlIHRoZW0uIil9YAoKRGF0YXRhYmxlIG9mIGFsbCBRQyBtZXRyaWNzOgpgYGB7cn0Kc2NlID0gY2FsY3VsYXRlX1FDX21ldHJpY3Moc2NlKQppZighYWxsKGNvbFN1bXMoYXMuZGF0YS5mcmFtZShRQ19tZXRyaWNzKHNjZSkpKT4wKSl7CiAgUUNfbWV0cmljcyhzY2UpID0gUUNfbWV0cmljcyhzY2UpWywgY29sU3Vtcyhhcy5kYXRhLmZyYW1lKFFDX21ldHJpY3Moc2NlKSkpPjBdCn0KZGF0YXRhYmxlKGFzLmRhdGEuZnJhbWUoUUNfbWV0cmljcyhzY2UpKSwgd2lkdGg9ODAwLCBvcHRpb25zPWxpc3Qoc2Nyb2xsWD0gVFJVRSkpCmBgYAoKU3VtbWFyeSBvZiBhbGwgUUMgbWV0cmljczoKYGBge3J9CmRhdGF0YWJsZShkby5jYWxsKGNiaW5kLCBsYXBwbHkoUUNfbWV0cmljcyhzY2UpLCBzdW1tYXJ5KSksIHdpZHRoPTgwMCwgb3B0aW9ucz1saXN0KHNjcm9sbFg9IFRSVUUpKQpgYGAKCk51bWJlciBvZiByZWFkcyBtYXBwZWQgdG8gZXhvbiBiZWZvcmUgVU1JIGRlZHVwbGljYXRpb24gVlMgbnVtYmVyIG9mIGdlbmVzIGRldGVjdGVkOgpgYGB7cn0KZ2dwbG90bHkoZ2dwbG90KGFzLmRhdGEuZnJhbWUoUUNfbWV0cmljcyhzY2UpKSwgYWVzKHg9bWFwcGVkX3RvX2V4b24sIHk9bnVtYmVyX29mX2dlbmVzKSkrZ2VvbV9wb2ludChhbHBoYT0wLjgpKQprbml0cjo6a25pdF9leGl0KCkKYGBgCgojIFF1YWxpdHkgY29udHJvbAoKIyMgRGV0ZWN0IG91dGxpZXIgY2VsbHMKCkEgcm9idXN0aWZpZWQgTWFoYWxhbm9iaXMgRGlzdGFuY2UgaXMgY2FsY3VsYXRlZCBmb3IgZWFjaCBjZWxsIHRoZW4gb3V0bGllcnMgYXJlIGRldGVjdGVkIGJhc2VkIG9uIHRoZSBkaXN0YW5jZS4KSG93ZXZlciwgZHVlIHRvIHRoZSBjb21wbGV4IG5hdHVyZSBvZiBzaW5nbGUgY2VsbCB0cmFuc2NyaXB0b21lcyBhbmQgcHJvdG9jb2wgdXNlZCwgc3VjaCBhIG1ldGhvZCBjYW4gb25seSBiZSB1c2VkIHRvCmFzc2lzdCB0aGUgcXVhbGl0eSBjb250cm9sIHByb2Nlc3MuIFZpc3VhbCBpbnNwZWN0aW9uIG9mIHRoZSBxdWFsaXR5IGNvbnRyb2wgbWV0cmljcyBpcyBzdGlsbCByZXF1aXJlZC4gQnkgZGVmYXVsdCB3ZQp1c2UgYGNvbXAgPSAyYCBhbmQgdGhlIGFsZ29yaXRobSB3aWxsIHRyeSB0byBzZXBhcmF0ZSB0aGUgcXVhbGl0eSBjb250cm9sIG1ldHJpY3MgaW50byB0d28gZ2F1c3NpYW4gY2x1c3RlcnMuCgpUaGUgbnVtYmVyIG9mIG91dGxpZXJzOgpgYGB7cn0Kc2NlX3FjID0gZGV0ZWN0X291dGxpZXIoc2NlLCB0eXBlPSJsb3ciLCBjb21wID0gMikKdGFibGUoUUNfbWV0cmljcyhzY2VfcWMpJG91dGxpZXJzKQpgYGAKClBhaXJ3aXNlIHBsb3QgZm9yIFFDIG1ldHJpY3MsIGNvbG9yZWQgYnkgb3V0bGllcnM6CmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpwbG90X1FDX3BhaXJzKHNjZV9xYykKYGBgCgojIyBwbG90IGhpZ2hlc3QgZXhwcmVzc2lvbiBnZW5lcwoKUmVtb3ZlIGxvdyBxdWFsaXR5IGNlbGxzIGFuZCBwbG90IGhpZ2hlc3QgZXhwcmVzc2lvbiBnZW5lcy4KCmBgYHtyfQpzY2VfcWMgPSByZW1vdmVfb3V0bGllcnMoc2NlX3FjKQpzY2VfcWMgPSBjb252ZXJ0X2dlbmVpZChzY2VfcWMsIHJldHVybnM9ImV4dGVybmFsX2dlbmVfbmFtZSIpCnNjZV9xYyA8LSBjYWxjdWxhdGVRQ01ldHJpY3Moc2NlX3FjKQpwbG90UUMoc2NlX3FjLCB0eXBlID0gImhpZ2hlc3QtZXhwcmVzc2lvbiIsIG49MjApCmBgYAoKIyMgcmVtb3ZlIGxvdyBhYnVuZGFudCBnZW5lcwoKUGxvdCB0aGUgYXZlcmFnZSBjb3VudCBmb3IgZWFjaCBnZW5lczoKYGBge3J9CmF2ZS5jb3VudHMgPC0gcm93TWVhbnMoY291bnRzKHNjZV9xYykpCmhpc3QobG9nMTAoYXZlLmNvdW50cyksIGJyZWFrcz0xMDAsIG1haW49IiIsIGNvbD0iZ3JleTgwIiwKICAgICB4bGFiPWV4cHJlc3Npb24oTG9nWzEwXX4iYXZlcmFnZSBjb3VudCIpKQpgYGAKCkFzIGEgbG9vc2UgZmlsdGVyIHdlIGtlZXAgZ2VuZXMgdGhhdCBhcmUgZXhwcmVzc2VkIGluIGF0IGxlYXN0IHR3byBjZWxscyBhbmQgZm9yIGNlbGxzIHRoYXQgZXhwcmVzcyB0aGF0IGdlbmUsIHRoZQphdmVyYWdlIGNvdW50IGxhcmdlciB0aGFuIHR3by4gSG93ZXZlciB0aGlzIGlzIG5vdCB0aGUgZ29sZCBzdGFuZGFyZCBhbmQgdGhlIGZpbHRlciBtYXkgdmFyaXkgZGVwZW5kaW5nIG9uIHRoZSBkYXRhLgoKYGBge3J9CmtlZXAxID0gKGFwcGx5KGNvdW50cyhzY2VfcWMpLCAxLCBmdW5jdGlvbih4KSBtZWFuKHhbeD4wXSkpID4gMS4xKSAgIyBhdmVyYWdlIGNvdW50IGxhcmdlciB0aGFuIDEuMQprZWVwMiA9IChyb3dTdW1zKGNvdW50cyhzY2VfcWMpPjApID4gNSkgICMgZXhwcmVzc2VkIGluIGF0IGxlYXN0IDUgY2VsbHMKCnNjZV9xYyA9IHNjZV9xY1soa2VlcDEgJiBrZWVwMiksIF0KZGltKHNjZV9xYykKYGBgCgpXZSBnb3QgYHIgbnJvdyhzY2VfcWMpYCBnZW5lcyBsZWZ0IGFmdGVyIHJlbW92aW5nIGxvdyBhYnVuZGFudCBnZW5lcy4KCiMgRGF0YSBub3JtYWxpemF0aW9uCgojIyBOb3JtYWxpemF0aW9uIGJ5IGBzY3JhbmAgYW5kIGBzY2F0ZXJgCgpDb21wdXRlIHRoZSBub3JtYWxpemF0aW9uIHNpemUgZmFjdG9yCgpgYGB7cn0KbmNlbGxzID0gbmNvbChzY2VfcWMpCmlmIChuY2VsbHMgPiAyMDApIHsKICBzY2VfcWMgPC0gY29tcHV0ZVN1bUZhY3RvcnMoc2NlX3FjKQp9IGVsc2UgewogIHNjZV9xYyA8LSBjb21wdXRlU3VtRmFjdG9ycyhzY2VfcWMsIHNpemVzPWFzLmludGVnZXIoYyhuY2VsbHMvNywgbmNlbGxzLzYsIG5jZWxscy81LCBuY2VsbHMvNCwgbmNlbGxzLzMpKSkKfQpzdW1tYXJ5KHNpemVGYWN0b3JzKHNjZV9xYykpCmBgYAoKYHIgaWYgKG1pbihzaXplRmFjdG9ycyhzY2VfcWMpKSA8PSAwKXtwYXN0ZSgiV2UgaGF2ZSBuZWdhdGl2ZSBzaXplIGZhY3RvcnMgaW4gdGhlIGRhdGEuIFRoZXkgaW5kaWNhdGUgbG93IHF1YWxpdHkgY2VsbHMKYW5kIHdlIGhhdmUgcmVtb3ZlZCB0aGVtLiBUbyBhdm9pZCBuZWdhdGl2ZSBzaXplIGZhY3RvcnMsIHRoZSBiZXN0IHNvbHV0aW9uIGlzIHRvIGluY3JlYXNlIHRoZSBzdHJpbmdlbmN5IG9mIHRoZQpmaWx0ZXJpbmcuIil9YAoKYGBge3J9CmlmIChtaW4oc2l6ZUZhY3RvcnMoc2NlX3FjKSkgPD0gMCkgewogIHNjZV9xYyA9IHNjZV9xY1ssIHNpemVGYWN0b3JzKHNjZV9xYyk+MF0KfQpgYGAKClBDQSBwbG90IHVzaW5nIGdlbmUgZXhwcmVzc2lvbnMgYXMgaW5wdXQsIGNvbG9yZWQgYnkgdGhlIG51bWJlciBvZiBnZW5lcy4KCmBgYHtyfQpjcG0oc2NlX3FjKSA9IGNhbGN1bGF0ZUNQTShzY2VfcWMsIHVzZV9zaXplX2ZhY3RvcnM9RkFMU0UpCnBsb3RQQ0Eoc2NlX3FjLCBydW5fYXJncyA9IGxpc3QoZXhwcnNfdmFsdWVzPSJjcG0iKSwgY29sb3VyX2J5PSJ0b3RhbF9mZWF0dXJlcyIpCmBgYAoKIyMjIE5vcm1hbGl6ZSB0aGUgZGF0YSB1c2luZyBzaXplIGZhY3RvciBhbmQgZ2V0IGhpZ2ggdmFyaWFibGUgZ2VuZXMKClRoZSBoaWdobHkgdmFyaWFibGUgZ2VuZXMgYXJlIGNob3NlbiBiYXNlZCBvbiBgdHJlbmRWYXJgIGZyb20gYHNjcmFuYCB3aXRoIGBGRFIgPiAwLjA1YCBhbmQgYmlvbG9naWNhbCB2YXJpYXRpb24gbGFyZ2VyCnRoYW4gYDAuNWAuIElmIHRoZSBudW1iZXIgb2YgaGlnaGx5IHZhcmlhYmxlIGdlbmVzIGlzIHNtYWxsZXIgdGhhbiAxMDAgd2Ugd2lsbCBzZWxlY3QgdGhlIHRvcCAxMDAgZ2VuZXMgYnkgYmlvbG9naWNhbAp2YXJpYXRpb24uIElmIHRoZSBudW1iZXIgaXMgbGFyZ2VyIHRoYW4gNTAwIHdlIHdpbGwgb25seSBrZWVwIHRvcCA1MDAgZ2VuZXMgYnkgYmlvbG9naWNhbCB2YXJpYXRpb24uCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0Kc2NlX3FjIDwtIG5vcm1hbGl6ZShzY2VfcWMpCgp2YXIuZml0IDwtIHRyZW5kVmFyKHNjZV9xYywgbWV0aG9kPSJsb2VzcyIsIHVzZS5zcGlrZXM9RkFMU0UpCnZhci5vdXQgPC0gZGVjb21wb3NlVmFyKHNjZV9xYywgdmFyLmZpdCkKCmlmIChsZW5ndGgod2hpY2godmFyLm91dCRGRFIgPD0gMC4wNSAmIHZhci5vdXQkYmlvID49IDAuNSkpIDwgNTAwKXsKICBodmcub3V0IDwtIHZhci5vdXRbb3JkZXIodmFyLm91dCRiaW8sIGRlY3JlYXNpbmc9VFJVRSlbMTo1MDBdLCBdCn1lbHNlIGlmKGxlbmd0aCh3aGljaCh2YXIub3V0JEZEUiA8PSAwLjA1ICYgdmFyLm91dCRiaW8gPj0gMC41KSkgPiAxMDAwKXsKICBodmcub3V0IDwtIHZhci5vdXRbb3JkZXIodmFyLm91dCRiaW8sIGRlY3JlYXNpbmc9VFJVRSlbMToxMDAwXSwgXQp9ZWxzZXsKICBodmcub3V0IDwtIHZhci5vdXRbd2hpY2godmFyLm91dCRGRFIgPD0gMC4wNSAmIHZhci5vdXQkYmlvID49IDAuNSksIF0KICBodmcub3V0IDwtIGh2Zy5vdXRbb3JkZXIoaHZnLm91dCRiaW8sIGRlY3JlYXNpbmc9VFJVRSksIF0KfQoKcGxvdCh2YXIub3V0JG1lYW4sIHZhci5vdXQkdG90YWwsIHBjaD0xNiwgY2V4PTAuNiwgeGxhYj0iTWVhbiBsb2ctZXhwcmVzc2lvbiIsCiAgICAgeWxhYj0iVmFyaWFuY2Ugb2YgbG9nLWV4cHJlc3Npb24iKQpvIDwtIG9yZGVyKHZhci5vdXQkbWVhbikKbGluZXModmFyLm91dCRtZWFuW29dLCB2YXIub3V0JHRlY2hbb10sIGNvbD0iZG9kZ2VyYmx1ZSIsIGx3ZD0yKQpwb2ludHModmFyLm91dCRtZWFuW3Jvd25hbWVzKHZhci5vdXQpICVpbiUgcm93bmFtZXMoaHZnLm91dCldLCB2YXIub3V0JHRvdGFsW3Jvd25hbWVzKHZhci5vdXQpICVpbiUgcm93bmFtZXMoaHZnLm91dCldLCBjb2w9InJlZCIsIHBjaD0xNikKYGBgCgojIyBIZWF0bWFwIG9mIHRvcDEwMCBoaWdoIHZhcmlhYmxlIGdlbmVzCgpgYGB7cn0KZ2VuZV9leHAgPSBleHBycyhzY2VfcWMpCgpnZW5lX2V4cCA9IGdlbmVfZXhwW3Jvd25hbWVzKGh2Zy5vdXQpWzE6MTAwXSwgXQoKaGMucm93cyA8LSBoY2x1c3QoZGlzdChnZW5lX2V4cCkpCmhjLmNvbHMgPC0gaGNsdXN0KGRpc3QodChnZW5lX2V4cCkpKQoKZ2VuZV9leHAgPSBnZW5lX2V4cFtoYy5yb3dzJG9yZGVyLCBoYy5jb2xzJG9yZGVyXQoKbSA9IGxpc3QoCiAgbCA9IDEwMCwKICByID0gNDAsCiAgYiA9IDEwLAogIHQgPSAxMCwKICBwYWQgPSAwCikKCnBsb3RfbHkoCiAgICB4ID0gY29sbmFtZXMoZ2VuZV9leHApLCB5ID0gcm93bmFtZXMoZ2VuZV9leHApLAogICAgeiA9IGdlbmVfZXhwLCB0eXBlID0gImhlYXRtYXAiKSU+JQpsYXlvdXQoYXV0b3NpemUgPSBGLCBtYXJnaW4gPSBtKQpgYGAKCiMgRGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIHVzaW5nIGhpZ2ggdmFyaWFibGUgZ2VuZXMKCiMjIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBieSBQQ0EKCmBgYHtyfQpwbG90UENBKHNjZV9xYywgcnVuX2FyZ3MgPSBsaXN0KGV4cHJzX3ZhbHVlcz0ibG9nY291bnRzIiksIGNvbG91cl9ieT0idG90YWxfZmVhdHVyZXMiKQpgYGAKCiMjIERpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBieSB0LVNORQoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0zLjV9CnNldC5zZWVkKDEwMCkKaWYgKGFueShkdXBsaWNhdGVkKHQobG9nY291bnRzKHNjZV9xYylbcm93bmFtZXMoaHZnLm91dCksIF0pKSkpIHsKICBzY2VfcWMgPSBzY2VfcWNbLCAhZHVwbGljYXRlZCh0KGxvZ2NvdW50cyhzY2VfcWMpW3Jvd25hbWVzKGh2Zy5vdXQpLCBdKSldCn0Kb3V0NSA8LSBwbG90VFNORShzY2VfcWMsIHJ1bl9hcmdzID0gbGlzdChleHByc192YWx1ZXM9ImxvZ2NvdW50cyIsIHBlcnBsZXhpdHk9MTAsZmVhdHVyZV9zZXQ9cm93bmFtZXMoaHZnLm91dCkpLCBjb2xvdXJfYnk9InRvdGFsX2ZlYXR1cmVzIikgKyBnZ3RpdGxlKCJQZXJwbGV4aXR5ID0gMTAiKQpvdXQxMCA8LSBwbG90VFNORShzY2VfcWMsIHJ1bl9hcmdzID0gbGlzdChleHByc192YWx1ZXM9ImxvZ2NvdW50cyIsIHBlcnBsZXhpdHk9MjAsZmVhdHVyZV9zZXQ9cm93bmFtZXMoaHZnLm91dCkpLCBjb2xvdXJfYnk9InRvdGFsX2ZlYXR1cmVzIiwKICAgICBmZWF0dXJlX3NldD1yb3duYW1lcyhodmcub3V0KSkgICsgZ2d0aXRsZSgiUGVycGxleGl0eSA9IDIwIikKb3V0MjAgPC0gcGxvdFRTTkUoc2NlX3FjLCBydW5fYXJncyA9IGxpc3QoZXhwcnNfdmFsdWVzPSJsb2djb3VudHMiLCBwZXJwbGV4aXR5PTMwLGZlYXR1cmVfc2V0PXJvd25hbWVzKGh2Zy5vdXQpKSwgY29sb3VyX2J5PSJ0b3RhbF9mZWF0dXJlcyIsCiAgICAgZmVhdHVyZV9zZXQ9cm93bmFtZXMoaHZnLm91dCkpICArIGdndGl0bGUoIlBlcnBsZXhpdHkgPSAzMCIpCm11bHRpcGxvdChvdXQ1LCBvdXQxMCwgb3V0MjAsIGNvbHM9MykKYGBgCg==